#include "audio_encoder.h"
#include "esp_audio_enc.h"
#include "esp_audio_enc_default.h"
#include "esp_audio_enc_reg.h"
#include <stdlib.h>
#include <string.h>
#include <esp_err.h>
#include <esp_log.h>
#include "bsp_config.h"
#include <esp_heap_caps.h>

#define TAG "[AUDIO_PROCESSOR] Encoder"

struct audio_encoder
{
    esp_audio_enc_handle_t encoder;
    bool is_running;

    RingbufHandle_t input_buf;
    RingbufHandle_t output_buf;
};

static void copy_from_ringbuf(uint8_t *buf, int size, RingbufHandle_t ringbuf)
{
    uint8_t *read_buf = NULL;
    size_t read_size = 0;
    while (size > 0)
    {
        read_buf = xRingbufferReceiveUpTo(ringbuf, &read_size, portMAX_DELAY, size);
        assert(read_buf);

        memcpy(buf, read_buf, read_size);
        vRingbufferReturnItem(ringbuf, read_buf);
        buf += read_size;
        size -= read_size;
    }
}

static void audio_encoder_task(void *arg)
{
    ESP_LOGI(TAG, "Encoder task created");
    audio_encoder_t *audio_encoder = (audio_encoder_t *)arg;
    esp_audio_enc_handle_t encoder = audio_encoder->encoder;

    // 从环形缓存中读取数据，编码并写出
    int read_size = 0;
    int write_size = 0;
    ESP_ERROR_CHECK(esp_audio_enc_get_frame_size(encoder, &read_size, &write_size));

    uint8_t *input_buf = (uint8_t *)heap_caps_malloc(read_size, MALLOC_CAP_SPIRAM);
    assert(input_buf);

    uint8_t *output_buf = (uint8_t *)heap_caps_malloc(write_size, MALLOC_CAP_SPIRAM);
    assert(output_buf);

    esp_audio_enc_in_frame_t in_frame = {
        .buffer = input_buf,
        .len = read_size,
    };

    esp_audio_enc_out_frame_t out_frame = {
        .buffer = output_buf,
        .len = write_size,
    };

    while (audio_encoder->is_running)
    {
        // 从输入缓存中读取数据
        copy_from_ringbuf(input_buf, read_size, audio_encoder->input_buf);

        // 编码数据
        ESP_ERROR_CHECK(esp_audio_enc_process(encoder, &in_frame, &out_frame));

        // 写出编码后的数据
        assert(xRingbufferSend(audio_encoder->output_buf, output_buf, out_frame.encoded_bytes, portMAX_DELAY) == pdTRUE);
    }
    free(input_buf);
    free(output_buf);
    vTaskDelete(NULL);
}

audio_encoder_t *audio_encoder_create(void)
{
    audio_encoder_t *audio_encoder = (audio_encoder_t *)malloc(sizeof(audio_encoder_t));
    assert(audio_encoder);

    // 注册默认编码器
    ESP_ERROR_CHECK(esp_opus_enc_register());

    // 生成配置文件
    esp_opus_enc_config_t opus_config = {
        .application_mode = ESP_OPUS_ENC_APPLICATION_AUDIO,
        .bitrate = 32000,
        .bits_per_sample = BSP_CODEC_BIT_PER_SAMPLE,
        .channel = BSP_CODEC_CHANNEL_COUNT,
        .complexity = 6,
        .enable_dtx = false,
        .enable_fec = true,
        .enable_vbr = true,
        .frame_duration = ESP_OPUS_ENC_FRAME_DURATION_60_MS,
        .sample_rate = BSP_CODEC_SAMPLE_RATE,
    };

    esp_audio_enc_config_t enc_config = {
        .type = ESP_AUDIO_TYPE_OPUS,
        .cfg = &opus_config,
        .cfg_sz = sizeof(esp_opus_enc_config_t),
    };
    ESP_ERROR_CHECK(esp_audio_enc_open(&enc_config, &audio_encoder->encoder));

    // 创建编码器

    return audio_encoder;
}

void audio_encoder_start(audio_encoder_t *audio_encoder)
{
    audio_encoder->is_running = true;
    assert(xTaskCreatePinnedToCoreWithCaps(audio_encoder_task, "enc_task", 1024 * 32, audio_encoder, 5, NULL, 1, MALLOC_CAP_SPIRAM) == pdTRUE);
}

void audio_encoder_set_input_buffer(audio_encoder_t *audio_encoder, RingbufHandle_t buf)
{
    assert(audio_encoder);
    assert(buf);
    audio_encoder->input_buf = buf;
}

void audio_encoder_set_output_buffer(audio_encoder_t *audio_encoder, RingbufHandle_t buf)
{
    assert(audio_encoder);
    assert(buf);
    audio_encoder->output_buf = buf;
}
